<template>
  <el-upload
      class="upload-demo"
      drag
      :data="policyData"
      :action="policyData.host"
      :before-upload="handleBeforeUpload"
      :on-preview="handlePreview"
      :on-success="handleSuccess"
      :on-error="handleError"
      method="post"
      multiple
  >
    <el-icon class="el-icon--upload">
      <upload-filled/>
    </el-icon>
    <div class="el-upload__text">
      拖拽文件到这 或者 <em>点击上传</em>
    </div>
    <template #tip>
      <div class="el-upload__tip">
        只能上传jpg/png文件,且文件大小最好不要超过50MB
      </div>
    </template>
  </el-upload>
</template>

<script setup lang="ts">
import {reactive, ref} from "vue";
import {generatePolicy} from "@/api/upload/upload";
import {UploadFilled} from '@element-plus/icons-vue'
import {ElMessage, UploadProps, UploadUserFile} from "element-plus";

// 在给OSS的参数中需要OSSAccessKeyId和key参数，其中OSSAccessKeyId的值就是accessId，key表示上传到Bucket内的Object的完整路径
const policyData = reactive({
  OSSAccessKeyId: '',
  policy: '',
  signature: '',
  key: '',
  dir: '',
  host: '',
  expire: ''
})

// 在上传组件中绑定data可以在上传时附带的额外参数，我们服务端签名直传需要传递签名等信息给阿里云OSS
const fileList = reactive<UploadUserFile[]>([])

// 生成上传签名,参数为上传的文件
// 笔记：服务端签名直传过程会涉及跨域问题，我们必须将对应的bucket设置为允许跨域，位置在对应bucket空间下的数据安全中的跨域设置
const handleBeforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
  console.log("选中的上传文件为:" + rawFile.name, rawFile.size, rawFile.type)
  generatePolicy()
      .then(response => {
        console.log("获取签名响应数据: ", response.data)
        const {accessId, policy, signature, dir, host, expire} = response.data
        policyData.policy = policy
        policyData.signature = signature
        policyData.OSSAccessKeyId = accessId
        // key表示上传到Bucket内的Object的完整路径，例如exampledir/exampleobject.txtObject，完整路径中不能包含Bucket名称。
        // filename表示待上传的本地文件名称。
        policyData.key = (dir + `${rawFile.name}`)
        policyData.dir = dir
        policyData.host = host
        policyData.expire = expire
        return true;
      }).catch(error => {
    console.log("获取签名数据失败: ", error)
    return false;
  })
}

// 上传成功处理，主要工作是填充fileList数据
const handleSuccess: UploadProps['onSuccess'] = (response, uploadFile, uploadFiles) => {
  console.log(response, uploadFile, uploadFiles)
  console.log("上传成功，上传的文件为:", uploadFile)
  ElMessage({
    type: "success",
    message: "上传成功"
  })
  fileList.push(
      {
        name: uploadFile.name,
        url: policyData.host + policyData.dir + uploadFile.name
      }
  )
  console.log("fileList数据大小:", fileList.length)
}

// 点击已上传的预览文件
const handlePreview: UploadProps['onPreview'] = (file) => {
  console.log("handlePreview" + file)
}

// 上传失败处理，可以根据error的信息进行弹窗提示
const handleError: UploadProps['onError'] = (error, uploadFile, uploadFiles) => {
  ElMessage({
    type: "error",
    message: "上传失败"
  })
  console.log(error, uploadFile, uploadFiles)
}

</script>
